/**
 * DESC: Tests line drawing using Bresenham algorithm.
 *
 * IMP: HIGH
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>

#include <object.h>
#include <line.h>
#include <surface.h>
#include <visual.h>

#include <debug.h>
#include <unittest.h>


int main( int argc, char *argv[] )
{
  debug_level = 0; /* 1 = warn, 2 = info, 3 = verbose, 4 = debug mode */

  printf( "Bresenham line drawing test.\n" );
  printf( "Press any key to go next test step.\n" );


  visual_init( 800, 600 );

  line_draw_aliased = line_draw_bresenham;

  coord_t p = { 0, 0 };
  surface_t *s = surface_new( 800, 600 );
  assert_not_null( s );


  line_t *l = line_new();
  assert_not_null( l );

  color_t c;
  COLOR_FROM_ARGB( c, COLOR_RED );
  object_init2( l, c );

  printf( "2 diagonal red lines with 2 green lines, "
	  "one vertical and one horizontal.\n"
	  "Other lines are magenta and cyan, they have 10 pixel offset, "
	  "there are 4 of each, one in each side.\n" );

  /* diagonal lines */
  COLOR_FROM_ARGB( c, COLOR_RED );
  SET_RECT( l->r, 0, 0, 800, 600 );
  object_draw( l, s );

  SET_RECT( l->r, 0, 600, 800, 0 );
  object_draw( l, s );

  /* vertical and horizontal lines */
  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_GREEN );
  SET_RECT( l->r, 0, 300, 800, 300 );
  object_draw( l, s );

  SET_RECT( l->r, 400, 0, 400, 600 );
  object_draw( l, s );

  /* other lines */
  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_MAGENTA );
  SET_RECT( l->r, 0, 0, 10, 600 );
  object_draw( l, s );

  SET_RECT( l->r, 0, 0, 800, 10 );
  object_draw( l, s );

  SET_RECT( l->r, 790, 0, 800, 600 );
  object_draw( l, s );

  SET_RECT( l->r, 0, 590, 800, 600 );
  object_draw( l, s );


  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_CYAN );
  SET_RECT( l->r, 10, 0, 0, 600 );
  object_draw( l, s );

  SET_RECT( l->r, 0, 10, 800, 0 );
  object_draw( l, s );

  SET_RECT( l->r, 800, 0, 790, 600 );
  object_draw( l, s );

  SET_RECT( l->r, 0, 600, 800, 590 );
  object_draw( l, s );


  visual_display( s, p );
  visual_update();
  visual_waitkey();

  surface_clear( s );

  printf( "Yellow lines with 10px interval, begin at ( 0, 0 )\n" );

  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_YELLOW );
  {
    uint16_t i;
    for ( i=0; i < 600; i += 10 )
      {
	SET_RECT( l->r, 0, 0, 800, i );
	object_draw( l, s );
      }
    for ( i=0; i <= 800; i += 10 )
      {
	SET_RECT( l->r, 0, 0, i, 600 );
	object_draw( l, s );
      }
  }

  visual_display( s, p );
  visual_update();
  visual_waitkey();

  surface_clear( s );

  printf( "Yellow lines with 10px interval, begin at ( 0, 600 )\n" );

  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_YELLOW );
  {
    uint16_t i;
    for ( i=0; i < 600; i += 10 )
      {
	SET_RECT( l->r, 0, 600, 800, i );
	object_draw( l, s );
      }
    for ( i=0; i <= 800; i += 10 )
      {
	SET_RECT( l->r, 0, 600, i, 0 );
	object_draw( l, s );
      }
  }

  visual_display( s, p );
  visual_update();
  visual_waitkey();

  surface_clear( s );

  printf( "Sanity check: line from ( 800, 600 ) to ( 0, 0 ).\n" );

  /*
   * draw line with inversed x (x1 < x0 )
   */
  /* diagonal line */
  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_RED );
  SET_RECT( l->r, 800, 600, 0, 0 );
  object_draw( l, s );

  visual_display( s, p );
  visual_update();
  visual_waitkey();

  printf( "Sanity check: now the other red line and the 2 green.\n" );

  SET_RECT( l->r, 800, 0, 0, 600 );
  object_draw( l, s );

  /* vertical and horizontal lines */
  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_GREEN );
  SET_RECT( l->r, 800, 300, 0, 300 );
  object_draw( l, s );

  SET_RECT( l->r, 400, 600, 400, 0 );
  object_draw( l, s );

  visual_display( s, p );
  visual_update();
  visual_waitkey();

  COLOR_FROM_ARGB( OBJECT_COLOR( l ), COLOR_GREEN );
  SET_RECT( l->r, 800, 600, 0, 600 );
  object_draw( l, s );

  visual_display( s, p );
  visual_update();
  visual_waitkey();

  surface_free( s );
  object_free( l );

  visual_quit();

  return ask_user_yn( "Everything rendered as expect?" ) != 1;
}
